package cn.itcast.service.impl;

import cn.itcast.dao.ReportDao;
import cn.itcast.pojo.ExcelHead;
import cn.itcast.service.ReportService;
import cn.itcast.util.CustomCellWriteHandler;
import cn.itcast.util.MyMergeStrategy;
import cn.itcast.utils.DateUtils;
import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.merge.LoopMergeStrategy;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.util.CellRangeAddress;
import org.springframework.beans.factory.annotation.Autowired;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;


@Service
public class ReportServiceImpl implements ReportService {

    @Autowired
    private ReportDao reportDao;
    @Override
    public Map<String, Object> reportMemberCount() {
        //计算离现在最近的12个月
        //获取当前时间
        Date date = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM");
        //将当前时间转为"yyyy-MM"格式
        String now = simpleDateFormat.format(date);
        //切割获取当前年和当前月
        String[] split = StringUtils.split(now,"-");
        Integer year = Integer.valueOf(split[0]);
        Integer month = Integer.valueOf(split[1]);
        //创建封装过去12月的数据的数组
        Date[] months1 = new Date[12];
        //封装过去的12个月到数据中
        for (int i = 0; i < 12; i++) {
            if(month > 0){
                String mon = year + "-" + month;
                try {
                    Date parse = simpleDateFormat.parse(mon);
                    months1[11 - i] = parse;
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }else{
                month = 12;
                year = year - 1;
                String mon = year + "-" + month;
                try {
                    Date parse = simpleDateFormat.parse(mon);
                    months1[11 - i] = parse;
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }
            month--;
        }
        String[] months = new String[12];
        //遍历数组查询数据库对应的会员数量，并封装到另一个数组中
        Integer[] memberCount = new Integer[12];
        for (int i = 0; i < months1.length; i++) {
            String format = simpleDateFormat.format(months1[i]);
            months[i] = format;

            Integer count = reportDao.reportMemberCount(format);
            memberCount[i] = count;
        }
        //封装数据
        Map<String,Object> date1 = new HashMap();

        date1.put("months",months);
        date1.put("memberCount",memberCount);

        return date1;
    }

    @Override
    public Map<String, Object> reportSetmeals() {
        //查询数据库，查询已经预约的种类及其数量
        List<Map> maps = reportDao.reportSetmeals();
        String[] Names = new String[maps.size()];
        Map[] Counts = new Map[maps.size()];
        String[] remarks = new String[maps.size()];
        for (int i = 0; i < maps.size(); i++) {
            Map map = maps.get(i);
            String setmealNames = (String) map.get("name");
            Long value = (Long) map.get("value");
            String remark = (String) map.get("remark");
            Map<String,Object> countsMap = new HashMap<>();
            countsMap.put("name",setmealNames);
            countsMap.put("value",value);
            remarks[i] = remark;
            Names[i] = setmealNames;
            Counts[i] = countsMap;
        }
        Map<String,Object> map = new HashMap<>();
        map.put("setmealNames",Names);
        map.put("setmealCount",Counts);
        map.put("remark",remarks);
        return map;
    }

    @Override
    public Map<String, Object> reportBusiness() {
        //创建一个封装数据的集合
        Map<String , Object> map = new HashMap<>();
        //获取当前时间
        Date date = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        //转换为当前日期
        String today = simpleDateFormat.format(date);
        //查询今天新增的会员数量
        Integer todayNewMember = reportDao.selectTodayNewMember(today);
        //查询总会员数量
        Integer totalMember = reportDao.selectTotalMember();
        //查询本周新增会员数量
        //获取当前时间
        Calendar calendar = Calendar.getInstance();
        //获取到当前是这周的第几天
        int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK ) -1;
        if(dayOfWeek == 0){
            dayOfWeek = 7;
        }
        //获取当前是这月的第几天
        int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
        //获取到当前月
        int month = calendar.get(Calendar.MONTH) + 1;
        //获取当前年
        int year = calendar.get(Calendar.YEAR);
        //获取本周的第一天的日期
        int firstDayOfMonth = dayOfMonth - (dayOfWeek - 1);

        SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM");
        //如果当前月的天数小于星期的天数，往上个月挪
        if(dayOfMonth - (dayOfWeek - 1) <= 0){
            month = month - 1;
            //如果是第一个月,往前一年挪
            if(month <= 0){
                month = 12;
                year = year - 1;
            }
            Date parse = null;
            try {
                parse = simpleDateFormat1.parse(year + "-" + month);
            } catch (ParseException e) {
                e.printStackTrace();
            }
            calendar.setTime(parse);
            //获取前一月的天数
            int actualMaximum = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
            //计算相差天数
            int i = (dayOfWeek - 1) - dayOfMonth;
            //计算本周第一天的日期
            firstDayOfMonth = actualMaximum - i;
        }
        //本周第一天的年月日(可能存在月份为个位数，格式里没0)
        String firstDay = year + "-" + month +  "-" + firstDayOfMonth;
        Date parse = null;
        try {
            parse = simpleDateFormat.parse(firstDay);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        //完善格式(本周的第一天)
        firstDay = simpleDateFormat.format(parse);
        //获取本周的最后一天
        Date sundayOfThisWeek = DateUtils.getSundayOfThisWeek();
        String lastDay = simpleDateFormat.format(sundayOfThisWeek);
        //获取本周新增的会员数
        Integer thisWeekNewMember = reportDao.selectWeekNewMember(firstDay,lastDay);
        //获取本月的日期
        String monthOfYear = simpleDateFormat1.format(date);
        //获取本月新增的会员数
        Integer thisMonthNewMember = reportDao.selectMonthNewMember(monthOfYear);
        //获取今日预约数
        Integer todayOrderNumber = reportDao.selectTodayOrderCount(today);
        //获取今日到诊数
        Integer todayVisitsNumber = reportDao.selectTodayArrival(today);
        //获取本周预约数
        Integer thisWeekOrderNumber = reportDao.selectWeekOrderCount(firstDay , lastDay);
        //获取本周到诊数
        Integer thisWeekVisitsNumber = reportDao.selectThisWeekVisitsNumber(firstDay,lastDay);
        //获取本月预约数
        Integer thisMonthOrderNumber = reportDao.selectThisMonthOrderNumber(monthOfYear);
        //获取本月到诊数
        Integer thisMonthVisitsNumber = reportDao.selectThisMonthVisitsNumber(monthOfYear);

        List<Map> hotSetmeal = new ArrayList<>();
        Map<String, Object> setmeals = this.reportSetmeals();
        Map[] setmealCount = (Map[]) setmeals.get("setmealCount");
        String[] remarks = (String[]) setmeals.get("remark");
        //计算预约总数
        Long sum = 0L;
        for (Map map1 : setmealCount) {
            Long value = (Long) map1.get("value");
            sum += value;
        }
        for (int i = 0; i < setmealCount.length; i++) {
            Map<String,Object> map2 = new HashMap<>();
            String name = (String) setmealCount[i].get("name");
            Long value = (Long) setmealCount[i].get("value");
            String remark = remarks[i];
            map2.put("name",name);
            map2.put("setmeal_count",value);
            map2.put("remark",null);
            double a = ((double)value)/((double)sum) * 100;
            BigDecimal bigDecimal = new BigDecimal(a);
            double v = bigDecimal.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
            map2.put("proportion",v);
            hotSetmeal.add(map2);
        }

        //封装数据
        map.put("reportDate",today);
        map.put("todayNewMember",todayNewMember);
        map.put("totalMember",totalMember);
        map.put("thisWeekNewMember",thisWeekNewMember);
        map.put("thisMonthNewMember",thisMonthNewMember);
        map.put("todayOrderNumber",todayOrderNumber);
        map.put("todayVisitsNumber",todayVisitsNumber);
        map.put("thisWeekOrderNumber",thisWeekOrderNumber);
        map.put("thisWeekVisitsNumber",thisWeekVisitsNumber);
        map.put("thisMonthOrderNumber",thisMonthOrderNumber);
        map.put("thisMonthVisitsNumber",thisMonthVisitsNumber);
        map.put("hotSetmeal",hotSetmeal);

        return map;
    }

    @Override
    public Map<String, Object> reportIncome() {
        //计算离现在最近的12个月
        //获取当前时间
        Date date = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM");
        //将当前时间转为"yyyy-MM"格式
        String now = simpleDateFormat.format(date);
        //切割获取当前年和当前月
        String[] split = StringUtils.split(now,"-");
        Integer year = Integer.valueOf(split[0]);
        Integer month = Integer.valueOf(split[1]);
        //创建封装过去12月的数据的数组
        Date[] months1 = new Date[12];
        //封装过去的12个月到数据中
        for (int i = 0; i < 12; i++) {
            if(month > 0){
                String mon = year + "-" + month;
                try {
                    Date parse = simpleDateFormat.parse(mon);
                    months1[11 - i] = parse;
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }else{
                month = 12;
                year = year - 1;
                String mon = year + "-" + month;
                try {
                    Date parse = simpleDateFormat.parse(mon);
                    months1[11 - i] = parse;
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }
            month--;
        }
        String[] months = new String[12];
        //遍历数组查询数据库对应的会员数量，并封装到另一个数组中
        Integer[] income = new Integer[12];
        for (int i = 0; i < months1.length; i++) {
            String format = simpleDateFormat.format(months1[i]);
            months[i] = format;

            Integer money = reportDao.reportIncome(format);
            income[i] = money;
        }
        //封装数据
        Map<String,Object> date1 = new HashMap();

        date1.put("months",months);
        date1.put("money",income);

        return date1;
    }

    @Override
    public Map<String, Object> reportOrderAndPay() {
        //计算离现在最近的12个月
        //获取当前时间
        Date date = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM");
        //将当前时间转为"yyyy-MM"格式
        String now = simpleDateFormat.format(date);
        //切割获取当前年和当前月
        String[] split = StringUtils.split(now,"-");
        Integer year = Integer.valueOf(split[0]);
        Integer month = Integer.valueOf(split[1]);
        //创建封装过去12月的数据的数组
        Date[] months1 = new Date[12];
        //封装过去的12个月到数据中
        for (int i = 0; i < 12; i++) {
            if(month > 0){
                String mon = year + "-" + month;
                try {
                    Date parse = simpleDateFormat.parse(mon);
                    months1[11 - i] = parse;
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }else{
                month = 12;
                year = year - 1;
                String mon = year + "-" + month;
                try {
                    Date parse = simpleDateFormat.parse(mon);
                    months1[11 - i] = parse;
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }
            month--;
        }
        String[] months = new String[12];
        //遍历数组查询数据库对应的会员数量，并封装到另一个数组中
        Integer[] orderCount = new Integer[12];
        Integer[] payCount = new Integer[12];
        for (int i = 0; i < months1.length; i++) {
            String format = simpleDateFormat.format(months1[i]);
            months[i] = format;

            Integer oCount = reportDao.reportOrderCount(format);
            Integer pCount = reportDao.reportPayCount(format);
            orderCount[i] = oCount;
            payCount[i] = pCount;
        }
        //封装数据
        Map<String,Object> date1 = new HashMap();

        date1.put("months",months);
        date1.put("orderCount",orderCount);
        date1.put("payCount",payCount);

        return date1;
    }

    //导出excel
    @Override
    public Boolean exportBusiness() {
        Map<String, Object> map = this.reportBusiness();

        String template = Thread.currentThread().getContextClassLoader().getResource("static").getPath();
        String fileName = template + map.get("reportDate") + "运营数据统计" + ".xlsx";
        ExcelWriter excelWriter1 = null;
        try {
            List<ExcelHead> excelHeads = new ArrayList<>();
            ExcelHead excelHead1 = new ExcelHead("", "", "", "日期:" + map.get("reportDate"));
            excelHeads.add(excelHead1);

            ExcelHead excelHead2 = new ExcelHead("会员数据统计", null, null, null);
            ExcelHead excelHead3 = new ExcelHead("新增会员数",  map.get("todayNewMember")+"", "总会员数",  map.get("totalMember") + "");
            ExcelHead excelHead4 = new ExcelHead("本周新增会员数",  map.get("thisWeekNewMember") + "", "本月新增会员数",  map.get("thisMonthNewMember") + "");
            ExcelHead excelHead41 = new ExcelHead();
            excelHeads.add(excelHead2);
            excelHeads.add(excelHead3);
            excelHeads.add(excelHead4);
            excelHeads.add(excelHead41);

            ExcelHead excelHead5 = new ExcelHead("预约到诊数据统计", null, null, null);
            ExcelHead excelHead6 = new ExcelHead("今日预约数",  map.get("todayOrderNumber") + "", "今日到诊数",  map.get("todayVisitsNumber") + "");
            ExcelHead excelHead7 = new ExcelHead("本周预约数",  map.get("thisWeekOrderNumber") + "", "本周到诊数", map.get("thisWeekVisitsNumber" ) + "");
            ExcelHead excelHead8 = new ExcelHead("本月预约数",  map.get("thisMonthOrderNumber") + "", "本月到诊数", map.get("thisMonthVisitsNumber") + "");
            ExcelHead excelHead81 = new ExcelHead();
            excelHeads.add(excelHead5);
            excelHeads.add(excelHead6);
            excelHeads.add(excelHead7);
            excelHeads.add(excelHead8);
            excelHeads.add(excelHead81);

            List<Map> hotSetmeal = (List<Map>) map.get("hotSetmeal");
            excelHeads.add(new ExcelHead("热门套餐", null, null, null));
            excelHeads.add(new ExcelHead("套餐名称", "预约数量", "占比", "备注"));
            for (Map map1 : hotSetmeal) {
                String name = (String) map1.get("name");
                Long setmeal = (Long) map1.get("setmeal_count");
                double proportion1 = (double) map1.get("proportion") * 100;
                BigDecimal bigDecimal = new BigDecimal(proportion1);
                double v = bigDecimal.setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue();
                String proportion = (v + "%");
                String remark = (String) map1.get("remark");
                ExcelHead excelHead9 = new ExcelHead(name, setmeal + "", proportion, null);
                excelHeads.add(excelHead9);
            }

            //合并
            List<CellRangeAddress> list = new ArrayList<>();
            //合并第4行
            CellRangeAddress item1 = new CellRangeAddress(3, 3, 0, 3);
            //合并第8行
            CellRangeAddress item2 = new CellRangeAddress(7, 7, 0, 3);
            //合并第13行
            CellRangeAddress item3 = new CellRangeAddress(12, 12, 0, 3);
            list.add(item1);
            list.add(item2);
            list.add(item3);
            MyMergeStrategy myMergeStrategy = new MyMergeStrategy(list);

            //设置高亮
            Integer[] yellowRows = {3, 7, 12};
            Set<Integer> yellowRowsSet = new HashSet<>(Arrays.asList(yellowRows));
            CustomCellWriteHandler customCellWriteHandler = new CustomCellWriteHandler(yellowRowsSet);

            EasyExcel.write(fileName, ExcelHead.class)
                    .registerWriteHandler(customCellWriteHandler)
                    .registerWriteHandler(myMergeStrategy)
                    .sheet("统计").doWrite(excelHeads);

            return true;
        }catch (Exception e){
            e.printStackTrace();
        }
        return false;
    }
}
